Frames auto-sizing -- Solved!

I was beginning to feel like Harry Potter and The Mirror of Erised (see end of post for reference). I was getting wasted away before it.

I don't know if this behavior changed over time but in order to shrink frames down to the size of their contents I found I had to do:

DBE frame2 = frame(box, "Frame 2")
frame2->"top"->"flush"->frame1;
frame2->"left"->"form";
frame2->"right"->"form";
frame2->"bottom"->"aligned"->frame1;

For the first frame I had to toss in an anchor to grab onto at the top and do this for the very first:

 

DBE topSep = separator(box);
topSep->"top"->"form";
topSep->"left"->"form";
topSep->"right"->"form";
topSep->"bottom"->"unattached";
 
DBE frame1 = frame(box, "Frame 1")
frame1->"top"->"form";
frame1->"left"->"form";
frame1->"right"->"form";
frame1->"bottom"->"aligned"->topSep;


The good news is it seems to work like a champ now (with DOORS 9.3).

Any scientific explanations for why all this is necessary to toss a few GUI items in a frame?

DB  box;
DBE ceiling;
DBE frames[10];
DBE labels[50];
int frameIndex = -1;
int labelIndex = -1;
 
void addFrame() {
    frameIndex++;
    if (frameIndex == sizeof(frames)) {
        ack("increase frames array size!");
        destroy(box);
        halt();
    }
    frames[frameIndex] = frame(box, "Frame " (frameIndex) "");
    if (frameIndex == 0) {
        frames[frameIndex]->"top"->"form";
        frames[frameIndex]->"bottom"->"aligned"->ceiling;
    } else {
        frames[frameIndex]->"top"->"flush"->frames[frameIndex-1];
        frames[frameIndex]->"bottom"->"aligned"->frames[frameIndex-1];
    }
    frames[frameIndex]->"left"->"form";
    frames[frameIndex]->"right"->"form";
}
 
 
void addLabelsToFrame(int howMany) {
    int i;
    for (i = 0; i < howMany; i++) {
        labelIndex++;
        if (labelIndex == sizeof(labels)) {
            ack("increase labels array size!");
            destroy(box);
            halt();
        }
        labels[labelIndex] = label(box, "Label " (labelIndex) "");
        if (i == 0) {
            labels[labelIndex]->"top"->"inside"->frames[frameIndex];
        } else {
            labels[labelIndex]->"top"->"flush"->labels[labelIndex-1];
        }
        labels[labelIndex]->"left"->"inside"->frames[frameIndex];
        labels[labelIndex]->"right"->"inside"->frames[frameIndex];
        if (i == (howMany - 1)) {
            labels[labelIndex]->"bottom"->"inside"->frames[frameIndex];
        } else {
            labels[labelIndex]->"bottom"->"unattached";
        }
    }
}
 
void simpleFrame() {
    void closeDialog(DB box) {
        hide(box);
        destroy(box);
        //ack("Bye");
    }
 
    box = create("My Dialog");
    ceiling = separator(box);
 
    ceiling->"top"->"form";
    ceiling->"left"->"form";
    ceiling->"right"->"form";
    ceiling->"bottom"->"unattached";
 
    addFrame();
    addLabelsToFrame(3);
 
    addFrame();
    addLabelsToFrame(1);
 
    addFrame();
    addLabelsToFrame(20);
 
    // Don't want an auto-populated close button
    close(box, false, closeDialog);
 
    hide(ceiling);
    realize(box);
    show(box);
}
 
simpleFrame();


The Mirror of Erised is a mystical mirror discovered by Harry in a back corridor of Hogwarts in Philosopher's Stone. On it is inscribed "erised stra ehru oyt ube cafru oyt on wohsi." When mirrored and correctly spaced, this reads "I show not your face but your heart's desire." As "erised" reversed is "desire," it is the "mirror of desire." Harry, upon encountering the Mirror, can see his parents, as well as what appears to be a crowd of relatives; Ron sees himself as Head Boy and Quidditch Captain holding the House Cup (thus revealing his wish to be acknowledged out of the shadow of his highly successful older brothers, as well as his more popular friend, Harry). Dumbledore cautions Harry that the mirror gives neither knowledge nor truth and that men have wasted away before it, entranced by what they see.

COMMENT: I was not entranced by what I saw here, but I was going mad!

This is the solution to this http://www.ibm.com/developerworks/forums/thread.jspa?messageID=14731121

 

 


SystemAdmin - Wed Nov 30 16:37:09 EST 2011

Re: Frames auto-sizing -- Solved!
llandale - Thu Dec 01 15:42:14 EST 2011

Bottom Aligned with the one above it?!!? Will try to remember that one.

Re: Frames auto-sizing -- Solved!
SystemAdmin - Thu Dec 01 16:08:04 EST 2011

llandale - Thu Dec 01 15:42:14 EST 2011
Bottom Aligned with the one above it?!!? Will try to remember that one.

As I was integrating frame stuff into what I was working on, I found it broke something else. (as usual!) Packing the frames with the Bottom Aligned stunt will prohibit vertical growth. But I think I found a reasonable work-around.

DOORS default frame sizes seem to be about 5 text lines tall (not zero lines as I would expect). I don't know of any means to set the size.
 

  • Adding 5 or more lines?:
    • The default is fine. The frame will grow bigger if you add more.

 

  • Adding less than 5 lines and want to pack tightly vertically and don't mind if it can't be vertically stretched?:
    • Do something similar to the code in verticalPackFrame() below.
    • Side effect -- You can not enable dynamic growth with setExtraHeightShare. The frame will remain packed tightly.

 

 

  • Adding less than 5 lines and want to pack tightly vertically and want to the frame to participate in vertical dialog box stretching?:
    • You are out of luck (left as an exercise for the reader.)

 

 

DB  box;
DBE ceiling;
DBE frames[10];
DBE labels[50];
int frameIndex = -1;
int labelIndex = -1;
 
void addFrame() {
    frameIndex++;
    if (frameIndex == sizeof(frames)) {
        ack("increase frames array size!");
        destroy(box);
        halt();
    }
    frames[frameIndex] = frame(box, "Frame " (frameIndex) "");
    if (frameIndex == 0) {
        frames[frameIndex]->"top"->"form";
    } else {
        frames[frameIndex]->"top"->"flush"->frames[frameIndex-1];
    }
    frames[frameIndex]->"left"->"form";
    frames[frameIndex]->"right"->"form";
}
 
//------------------------------------------------------------------------------
// DOORS default frame sizes seem to be about 5 text lines tall.  I don't know
// of any means to set the size.
//------------------------------------------------------------------------------
// Adding 5 or more lines?:
//     The the default is fine.  The frame will grow bigger if you add more.
//---
// Adding less than 5 lines and want to pack tightly vertically and don't mind
// if it can't be vertically stretched?:
//     Call this routine.
//     Side effect -- You can not enable dynamic growth with setExtraHeightShare.
//                    The frame will remain packed tightly.
//---
// Adding less than 5 lines and want to pack tightly vertically and want to
// the frame to participate in vertical dialog box stretching?:
//     You are out of luck (left as an exercise for the reader.)
//------------------------------------------------------------------------------
void verticalPackFrame(int index) {
    if (index == 0) {
        frames[index]->"bottom"->"aligned"->ceiling;
    } else {
        frames[index]->"bottom"->"aligned"->frames[index-1];
    }
}
 
void addLabelsToFrame(int howMany) {
    int i;
    for (i = 0; i < howMany; i++) {
        labelIndex++;
        if (labelIndex == sizeof(labels)) {
            ack("increase labels array size!");
            destroy(box);
            halt();
        }
        labels[labelIndex] = label(box, "Label " (labelIndex) "");
        if (i == 0) {
            labels[labelIndex]->"top"->"inside"->frames[frameIndex];
        } else {
            labels[labelIndex]->"top"->"flush"->labels[labelIndex-1];
        }
        labels[labelIndex]->"left"->"inside"->frames[frameIndex];
        labels[labelIndex]->"right"->"inside"->frames[frameIndex];
        if (i == (howMany - 1)) {
            labels[labelIndex]->"bottom"->"inside"->frames[frameIndex];
        } else {
            labels[labelIndex]->"bottom"->"unattached";
        }
    }
}
 
void addButtonsToFrame() {
    void buttonDialog(DBE someButton) {
        ack("Button pressed")
    }
 
    DBE button1 = button(box, "Button 1", buttonDialog);
    DBE button2 = button(box, "Button 2", buttonDialog);
    DBE button3 = button(box, "Button 3", buttonDialog);
 
    button1->"top"->"inside"->frames[frameIndex];
    button1->"left"->"inside"->frames[frameIndex];
    button1->"right"->"unattached";
    button1->"bottom"->"inside"->frames[frameIndex];
 
    button2->"top"->"inside"->frames[frameIndex];
    button2->"left"->"spaced"->button1;
    button2->"right"->"unattached";
    button2->"bottom"->"inside"->frames[frameIndex];
 
    button3->"top"->"inside"->frames[frameIndex];
    button3->"left"->"spaced"->button2;
    button3->"right"->"inside"->frames[frameIndex];
    button3->"bottom"->"inside"->frames[frameIndex];
}
 
 
void simpleFrame() {
    void closeDialog(DB box) {
        hide(box);
        destroy(box);
    }
 
    box = create("My Dialog");
    // Don't want an auto-populated close button
    close(box, false, closeDialog);
 
    ceiling = separator(box);
 
    ceiling->"top"->"form";
    ceiling->"left"->"form";
    ceiling->"right"->"form";
    ceiling->"bottom"->"unattached";
 
    addFrame();
    addLabelsToFrame(1);
 
    addFrame();
    addLabelsToFrame(1);
 
    addFrame();
    addLabelsToFrame(1);
 
    addFrame();
    addButtonsToFrame();
 
    // pack frames 0, 3 (This can't grow if dialog gets stretched)
    verticalPackFrame(0);
    verticalPackFrame(3);
 
    hide(ceiling);
    realize(box);
 
    // frames 1 and 2 will share vertical growth
    // equally if dialog box gets stretched
    setExtraHeightShare(frames[1], 0.5);
    setExtraHeightShare(frames[2], 0.5);
 
    show(box);
}
 
simpleFrame();

 

Re: Frames auto-sizing -- Solved!
llandale - Thu Dec 01 17:12:19 EST 2011

SystemAdmin - Thu Dec 01 16:08:04 EST 2011

As I was integrating frame stuff into what I was working on, I found it broke something else. (as usual!) Packing the frames with the Bottom Aligned stunt will prohibit vertical growth. But I think I found a reasonable work-around.

DOORS default frame sizes seem to be about 5 text lines tall (not zero lines as I would expect). I don't know of any means to set the size.
 

  • Adding 5 or more lines?:
    • The default is fine. The frame will grow bigger if you add more.

 

  • Adding less than 5 lines and want to pack tightly vertically and don't mind if it can't be vertically stretched?:
    • Do something similar to the code in verticalPackFrame() below.
    • Side effect -- You can not enable dynamic growth with setExtraHeightShare. The frame will remain packed tightly.

 

 

  • Adding less than 5 lines and want to pack tightly vertically and want to the frame to participate in vertical dialog box stretching?:
    • You are out of luck (left as an exercise for the reader.)

 

 

DB  box;
DBE ceiling;
DBE frames[10];
DBE labels[50];
int frameIndex = -1;
int labelIndex = -1;
 
void addFrame() {
    frameIndex++;
    if (frameIndex == sizeof(frames)) {
        ack("increase frames array size!");
        destroy(box);
        halt();
    }
    frames[frameIndex] = frame(box, "Frame " (frameIndex) "");
    if (frameIndex == 0) {
        frames[frameIndex]->"top"->"form";
    } else {
        frames[frameIndex]->"top"->"flush"->frames[frameIndex-1];
    }
    frames[frameIndex]->"left"->"form";
    frames[frameIndex]->"right"->"form";
}
 
//------------------------------------------------------------------------------
// DOORS default frame sizes seem to be about 5 text lines tall.  I don't know
// of any means to set the size.
//------------------------------------------------------------------------------
// Adding 5 or more lines?:
//     The the default is fine.  The frame will grow bigger if you add more.
//---
// Adding less than 5 lines and want to pack tightly vertically and don't mind
// if it can't be vertically stretched?:
//     Call this routine.
//     Side effect -- You can not enable dynamic growth with setExtraHeightShare.
//                    The frame will remain packed tightly.
//---
// Adding less than 5 lines and want to pack tightly vertically and want to
// the frame to participate in vertical dialog box stretching?:
//     You are out of luck (left as an exercise for the reader.)
//------------------------------------------------------------------------------
void verticalPackFrame(int index) {
    if (index == 0) {
        frames[index]->"bottom"->"aligned"->ceiling;
    } else {
        frames[index]->"bottom"->"aligned"->frames[index-1];
    }
}
 
void addLabelsToFrame(int howMany) {
    int i;
    for (i = 0; i < howMany; i++) {
        labelIndex++;
        if (labelIndex == sizeof(labels)) {
            ack("increase labels array size!");
            destroy(box);
            halt();
        }
        labels[labelIndex] = label(box, "Label " (labelIndex) "");
        if (i == 0) {
            labels[labelIndex]->"top"->"inside"->frames[frameIndex];
        } else {
            labels[labelIndex]->"top"->"flush"->labels[labelIndex-1];
        }
        labels[labelIndex]->"left"->"inside"->frames[frameIndex];
        labels[labelIndex]->"right"->"inside"->frames[frameIndex];
        if (i == (howMany - 1)) {
            labels[labelIndex]->"bottom"->"inside"->frames[frameIndex];
        } else {
            labels[labelIndex]->"bottom"->"unattached";
        }
    }
}
 
void addButtonsToFrame() {
    void buttonDialog(DBE someButton) {
        ack("Button pressed")
    }
 
    DBE button1 = button(box, "Button 1", buttonDialog);
    DBE button2 = button(box, "Button 2", buttonDialog);
    DBE button3 = button(box, "Button 3", buttonDialog);
 
    button1->"top"->"inside"->frames[frameIndex];
    button1->"left"->"inside"->frames[frameIndex];
    button1->"right"->"unattached";
    button1->"bottom"->"inside"->frames[frameIndex];
 
    button2->"top"->"inside"->frames[frameIndex];
    button2->"left"->"spaced"->button1;
    button2->"right"->"unattached";
    button2->"bottom"->"inside"->frames[frameIndex];
 
    button3->"top"->"inside"->frames[frameIndex];
    button3->"left"->"spaced"->button2;
    button3->"right"->"inside"->frames[frameIndex];
    button3->"bottom"->"inside"->frames[frameIndex];
}
 
 
void simpleFrame() {
    void closeDialog(DB box) {
        hide(box);
        destroy(box);
    }
 
    box = create("My Dialog");
    // Don't want an auto-populated close button
    close(box, false, closeDialog);
 
    ceiling = separator(box);
 
    ceiling->"top"->"form";
    ceiling->"left"->"form";
    ceiling->"right"->"form";
    ceiling->"bottom"->"unattached";
 
    addFrame();
    addLabelsToFrame(1);
 
    addFrame();
    addLabelsToFrame(1);
 
    addFrame();
    addLabelsToFrame(1);
 
    addFrame();
    addButtonsToFrame();
 
    // pack frames 0, 3 (This can't grow if dialog gets stretched)
    verticalPackFrame(0);
    verticalPackFrame(3);
 
    hide(ceiling);
    realize(box);
 
    // frames 1 and 2 will share vertical growth
    // equally if dialog box gets stretched
    setExtraHeightShare(frames[1], 0.5);
    setExtraHeightShare(frames[2], 0.5);
 
    show(box);
}
 
simpleFrame();

 

So
  • bottom unattached gives minium height of 5 but allows setExtraHeightShare resizing, and
  • bottom aligned gives no minimum but disallows setExtraHeightShare resizing.

But wait! If you create the frame with width and height of 1, and use bottom unattached, then setExtraHeightShare seems to work and ballance is restored in the universe.

frames[frameIndex] = frame(box, "Frame " (frameIndex) "", 1, 1)

-Louie

Don't tease me with "left as an exercise" again!

Re: Frames auto-sizing -- Solved!
SystemAdmin - Fri Dec 02 12:26:01 EST 2011

llandale - Thu Dec 01 17:12:19 EST 2011
So

  • bottom unattached gives minium height of 5 but allows setExtraHeightShare resizing, and
  • bottom aligned gives no minimum but disallows setExtraHeightShare resizing.

But wait! If you create the frame with width and height of 1, and use bottom unattached, then setExtraHeightShare seems to work and ballance is restored in the universe.

frames[frameIndex] = frame(box, "Frame " (frameIndex) "", 1, 1)

-Louie

Don't tease me with "left as an exercise" again!

Louie, thanks! I never though I'd be quoting Niccolo Machiavelli, but it seems with DXL "The end justifies the means".

The on-line documentation suggests (foolish me) that specifying optional width, height was for specifying size and the (box, label) signature was the auto-size variation.

If anyone writes "The Hitch-hikers's Guide to DXL", we'd change it to

  • If you leave out width, height, you'll a frame with about 5 text lines of height. It will expand if you add more. It will not shrink if you add less.
  • If you specify 1, 1 as the optional width, height you will get the advertized behavior of what is supposed to happen if no width, height is specified.


DXL Help:

 


 

 

frame

 

Declaration
DBE frame(DB box,
          string label
        [,int width,
           int height])

Operation

Creates a frame element in box, which can contain other elements. The label is the title of the frame; width and height specify the size of the frame in pixels. If width and height are omitted, the frame expands to fit the elements within it.

 

 



My code change (probably for every time I use frame) will be:

// This starts out as a deflated balloon and expands to added content.
frames[frameIndex] = frame(box, "Frame " (frameIndex) "", 1, 1);


Louie, what was that remark you made a few months ago that was something like the below?

Don't get stressed. Let yourself go. Relax. Pretend you are an art major trying to shape some clay. Squish it. Shape it. If you don't like what you see, smash it and start again.

(Louie, did you ever try this on your boss?)

 

Re: Frames auto-sizing -- Solved!
llandale - Fri Dec 02 14:10:22 EST 2011

SystemAdmin - Fri Dec 02 12:26:01 EST 2011

Louie, thanks! I never though I'd be quoting Niccolo Machiavelli, but it seems with DXL "The end justifies the means".

The on-line documentation suggests (foolish me) that specifying optional width, height was for specifying size and the (box, label) signature was the auto-size variation.

If anyone writes "The Hitch-hikers's Guide to DXL", we'd change it to

  • If you leave out width, height, you'll a frame with about 5 text lines of height. It will expand if you add more. It will not shrink if you add less.
  • If you specify 1, 1 as the optional width, height you will get the advertized behavior of what is supposed to happen if no width, height is specified.


DXL Help:

 


 

 

frame

 

Declaration
DBE frame(DB box,
          string label
        [,int width,
           int height])

Operation

Creates a frame element in box, which can contain other elements. The label is the title of the frame; width and height specify the size of the frame in pixels. If width and height are omitted, the frame expands to fit the elements within it.

 

 



My code change (probably for every time I use frame) will be:

// This starts out as a deflated balloon and expands to added content.
frames[frameIndex] = frame(box, "Frame " (frameIndex) "", 1, 1);


Louie, what was that remark you made a few months ago that was something like the below?

Don't get stressed. Let yourself go. Relax. Pretend you are an art major trying to shape some clay. Squish it. Shape it. If you don't like what you see, smash it and start again.

(Louie, did you ever try this on your boss?)

 

I think I suggested your stress level when dealing with DXL is reduced if you increase your serenity to accept things as they are and let go of how they should be ..err.. how you think they should be. Your lover's foibles are "eccentricities" and pleasantly "endearing", your former lover's foibles are "shortcomings" and stressfully "annoying". They are the same foibles, its your perspect that determines whether they're pleasant or stressful. Likewise with DXL.

The paragraphs in the DXL manual are "clues" not "rules". It doesn't matter if that statement is really true, it's useful. At least on Fridays.

These DXL statements are technically correct. They do expand to fit when you omit the size; only implying that it doesn't when you do. The 2nd sentance should, but need not, include phrase "the initial size", and the 3rd sentance should insert phrase "the frame starts with a minimum size and". The section on "contrained placement" should better explain what those commands do vis-a-vis individual DBEs; but that's impossible since nobody really knows due to the numerous <disallowed content detected> behaviors.

-Louie ... who just this week figured out what a "dash-space" does at the beginning of a line!

Are you asking me if I ever looked at my boss and decided to smash it and start again? I've been instructed not to comment on that litigation.

Re: Frames auto-sizing -- Solved!
llandale - Mon Dec 05 12:06:24 EST 2011

I've only played with frames a couple times before your thread so this has been a learning experience for just about everybody. Let me try to list some rules as I understand them so far, and after folks have at them we should end up with a good set of principles for dealing with frames.
  • frames come attached to the left and right of the "form".
  • To allow natural frame resizing:
    • frame should be declared with an initial small size, perhaps 1,1.
    • to allow resizing in a direction, that direction should be attached to the "form" or be "unattached" (generally the "bottom").
    • to disallow resizing in a direction, that direction should be fixed to something or that width or height should specify the actual size.
  • For DBEs wanting to be in the frame:
    • If any DBE edge is "inside" the frame, the entire DBE is "inside" the frame.
    • A DBE "top" or "left" edge "inside" the frame means "space" it to that edge of the frame.
    • A DBE "right" or "bottom" edge "inside the frame means resize the frame to be at least that size; and
for variable size DBEs: "space" that edge to the frame.
    • DBE edges should rarely be relative to the "form".
  • Frames with variable size DBEs attached to the frame should generally make use of the setExtraHeightShare and setExtraWidthShare perms relative to the frame, not the DBE.

  • Louie

Re: Frames auto-sizing -- Solved!
SystemAdmin - Mon Dec 05 13:55:06 EST 2011

llandale - Mon Dec 05 12:06:24 EST 2011
I've only played with frames a couple times before your thread so this has been a learning experience for just about everybody. Let me try to list some rules as I understand them so far, and after folks have at them we should end up with a good set of principles for dealing with frames.

  • frames come attached to the left and right of the "form".
  • To allow natural frame resizing:
    • frame should be declared with an initial small size, perhaps 1,1.
    • to allow resizing in a direction, that direction should be attached to the "form" or be "unattached" (generally the "bottom").
    • to disallow resizing in a direction, that direction should be fixed to something or that width or height should specify the actual size.
  • For DBEs wanting to be in the frame:
    • If any DBE edge is "inside" the frame, the entire DBE is "inside" the frame.
    • A DBE "top" or "left" edge "inside" the frame means "space" it to that edge of the frame.
    • A DBE "right" or "bottom" edge "inside the frame means resize the frame to be at least that size; and
for variable size DBEs: "space" that edge to the frame.
    • DBE edges should rarely be relative to the "form".
  • Frames with variable size DBEs attached to the frame should generally make use of the setExtraHeightShare and setExtraWidthShare perms relative to the frame, not the DBE.

  • Louie

Louie, thanks for summarizing.

Here are my assumptions about the DBE model. Most of the below is is a mix of help file descriptions and empirical behavioral observations.

ANYONE -- If you know otherwise, please correct.

  • 1 DBE's have four "nodes" that may be used for arrangement in a dialog box. These nodes are (left, right, top, and bottom).

  • 2 For each DBE, there is one set of nodes (left, right, top, and bottom) that may be used for spacing or alignment but not both.

  • 3 A new assignment overwrites a prior assignment. In other words, if you use a node in a spacing arrangement and later use the same node in an alignment, the later alignment will overwrite the prior value in the node.

  • 4 Alignments (empirical observation only) -- When aligning DBEs to each other, the target DBEs get their nodes populated, but the reference DBE does not. In other words, if you had 4 DBE's (A, B, C, and D) lined up left to right, you could top-align B to A, C to B, and D to C and still have A's top available for perhaps a spaced relationship with whatever is above it.

  • 5 Attachments (empirical observation only) -- When attaching DBE's to each other (frames and forms excluded), the attachment affects both nodes. In other words, if you did a spaced attach using DBE B's left as a target with DBE A as a reference, you can think of a string connecting DBE A's right node with DBE B's left node. Both DBE A's right node and DBE B's left node values will be overwritten.

  • Defaults -- There are connection defaults when DBE's are added to a box. I don't know what they are so I probably make more explicit assignments than necessary.

  • Unattached -- You can explicitly assign (left, right, top, and bottom) as unattached. This will cause that side to float. Typically, unattached is done to override an undesired default assignment.

If anyone has crafted a "DBE explorer" to illustrate the (left, right, top, and bottom) connections among DBE objects, please share. This would be a useful debugging tool for relationships gone wrong (marital relationships out of scope!)